org 7c00h  		; the code below run at memory 0x7c00
    jmp start
[BITS 16]
string: 
    db 'real mode:hello world...'
string_size equ 24

global MEMORY_SIZE

CYLINDER   equ      20
SECOTRS    equ      63
HEAD       equ      16
DEVICE     equ      0x80    ;hard disk
COPY_TIMES equ      10

SCREEN_POS:              ;screen position
    dw      0

DISK_NUM: 
    db     0

MEMORY_SIZE:
    db     0

start:
    mov ax,0
    mov ss,ax
    mov sp,0x7c00

    ;mov byte [DISK_NUM],dl
   
    ;call clear_screen   ;clear screen
    call copy_disk

    call init_string
    call show_string

    mov eax,0xe801
    int 0x15
    shl bx,6
    add ax,bx
    mov [MEMORY_SIZE],ax

    call protect_mode
    jmp $

 init_string:
    mov di,0  ;gpu offset
    ret

show_byte:
    push di
    push es
    push ds
    push cx
    push si
    ;ax is the value
    mov di,[SCREEN_POS]

    mov dx,0xb800  	;gpu adress
    mov es,dx

    mov dx,0x42 	;gpu ascii properties
two_hex:
    mov bl,al
    shr bl,4
    and bl,0xf

    cmp bl,10
    jl add_00
    jmp add_a0
add_00:
    add bl,'0'
    jmp add_end0
add_a0:
    add bl,('a'-10)
add_end0:
    mov byte [es:di],bl 
    add di,1
    mov [es:di],dx
    add di,1
    ;again
    mov bl,al
    and bl,0xf

    cmp bl,10
    jl add_0
    jmp add_a
add_0:
    add bl,'0'
    jmp add_end
add_a:
     
    add bl,('a'-10)

add_end:
    mov byte [es:di],bl 
    add di,1
     
    mov [es:di],dx

    add di,1
    mov [SCREEN_POS],di

    pop si
    pop cx
    pop ds
    pop es
    pop di

    ret

show_string:
    mov cx,string_size 		; get the string size

    mov ax,0
    mov ds,ax
    mov si,string

    mov bx,0xb800  	;gpu adress
    mov es,bx

    mov dx,0x42 	;gpu ascii properties

    mov di,[SCREEN_POS]
    ;mov di,0
    mov bx,0
loop:
    mov byte al,[ds:si]
    mov [es:di],al
    inc di

    mov [es:di],dx
    inc si
    inc di
    inc bx
    cmp bx,cx
    jl  loop

    mov [SCREEN_POS],di
    ret
copy_disk:
    ;copy disk data to target position
    mov ax,0x900
    mov es,ax
    mov bx,0
    mov si,bx  ;count numbers

    mov bx,0 ;move into [es:bx]
     
    mov di,2 ;first time ,read from sector 2
    jmp loop_front_panel

read_back_panel:
    mov di,1
loop_back_panel:
    shr bx,4
    mov ax,es
    add ax,bx
    mov es,ax   ;512B=0x200,just the high pos

    mov bx,0
    mov ah,02h
    mov al,1   ;read sector numbers 
    mov cx,si
    mov ch,cl

    ;copy the di value
    mov dx,di
    mov cl,dl  ;start from sector n

    mov dh,1    ;panel 1
    mov dl,DEVICE

disk_again:
    int 0x13      ;copy data to 0x9000
    jc  disk_again

    mov bx,512

    add di,1
    cmp di,(SECOTRS+1)
    jl  loop_back_panel

    add si,1
    cmp si,COPY_TIMES                ;6 times
    jl  read_front_panel
    ret
read_front_panel:
    mov di,1
loop_front_panel:
    shr bx,4
    mov ax,es
    add ax,bx
    mov es,ax   ;512B=0x200,just the high pos

    mov bx,0

    mov ah,02h
    mov al,1   ;read sector numbers
    mov cx,si
    mov ch,cl

    ;copy the di value
    mov dx,di
    mov cl,dl  ;start from sector n

    mov dh,0    ;panel 0
    mov dl,DEVICE

disk_again1:
    int 13h     ;copy data to 0x9000
    jc disk_again1

    mov bx,512
    add di,1
    cmp di,(SECOTRS+1)
    jl  loop_front_panel

    jmp  read_back_panel
    ret

disk_err:
    jmp $

[BITS 16]
clear_screen:
    mov ax,0xb800  	;gpu adress
    mov es,ax
    mov di,0

    mov ax,0
    mov bx,0
    mov cx,(80*25)
    
l1:
    mov byte [es:di],bl
    inc di

    mov byte [es:di],bl
    inc di

    inc ax
    cmp ax,cx
    jl  l1
    ret

protect_mode:
    cli       ;close interrupt

    ;mov byte ax,[DISK_NUM]
    ;call show_byte
    
    mov cx,16
    mov ax,0
    mov ds,ax
    mov si,0x9000
show_hex16:
    mov byte ax,[ds:si]
    inc si
    call show_byte
    loop show_hex16

    ;open a20       
    in  al,0x92  
    or  al,00000010b  
    out 0x92,al 

    ;load lgdt
    lgdt  [gdtr]  
   
    ;enable proctect protect_mode
    mov eax,cr0
    or  eax,0x1  
    mov cr0,eax

    mov eax,[MEMORY_SIZE]
    ;jmp dword 0x8:protect_code  ;cs:ip  cs=1 000b, gdt table = 1,etc code 
    jmp  0x8:0x9000
    ret
gdt:
    dd 0x00000000
    dd 0x00000000  ;null

    ;code
    dd 0x000007ff  
    dd 0x00c09a00 

    ;data
    dd 0x000007ff
    dd 0x00c09200 

    ;gpu  0xb8000
    dd 0x80000007
    dd 0x00c0920b

gdtr:
    dw (4*8-1) ;size start from 0
    dd gdt

times 510-($-$$) db 0 

dw  0xaa55


